Micron Document
🎖️GitЯра🎖️


Displaying Raw • Download

feature/discovery/src/commonMain/kotlin/org/meshtastic/feature/discovery/DiscoverySummaryGenerator.kt bf929c20f274232e0eb8ddc19b2dc82403e99e5b (bf929c20) Text, 9.46 KB

T8b949e/*
* Copyright (c) 2026 Meshtastic LLC
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
Tff7b72package T7ee787org.meshtastic.feature.discovery

Tff7b72import T7ee787org.koin.core.annotation.Single
Tff7b72import T7ee787org.meshtastic.core.common.util.NumberFormatter
Tff7b72import T7ee787org.meshtastic.core.database.entity.DiscoveryPresetResultEntity
Tff7b72import T7ee787org.meshtastic.core.database.entity.DiscoverySessionEntity
Tff7b72import T7ee787org.meshtastic.feature.discovery.ai.LoRaPresetReference

Tf0883e@Single
Tf0883e@SuppressTb4b4b4(Ta5d6ff"Ta5d6ffTooManyFunctionsTa5d6ff"Tb4b4b4)
Tff7b72class T56d364DiscoverySummaryGenerator Tb4b4b4{

Tff7b72fun Td2a8ffgenerateSessionSummaryTb4b4b4(
Te6edf3sessionTb4b4b4: Te6edf3DiscoverySessionEntityTb4b4b4,
Te6edf3presetResultsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DiscoveryPresetResultEntityTff7b72>Tb4b4b4,
Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3presetResultsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72return Ta5d6ff"Ta5d6ffNo presets were scanned during this session.Ta5d6ff"

Tff7b72val Te6edf3ranked Tff7b72=
Te6edf3presetResultsTb4b4b4.Te6edf3sortedWithTb4b4b4(
Te6edf3compareByDescendingTff7b72<Te6edf3DiscoveryPresetResultEntityTff7b72> Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3uniqueNodes Tb4b4b4}Tb4b4b4.Te6edf3thenBy Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3avgChannelUtilization Tb4b4b4}Tb4b4b4,
Tb4b4b4)
Tff7b72val Te6edf3best Tff7b72= Te6edf3rankedTb4b4b4.Te6edf3firstTb4b4b4(Tb4b4b4)

Tff7b72val Te6edf3lines Tff7b72= Te6edf3buildList Tb4b4b4{
Te6edf3addTb4b4b4(Te6edf3buildPresetComparisonLineTb4b4b4(Te6edf3bestTb4b4b4, Te6edf3presetResultsTb4b4b4)Tb4b4b4)
Tff7b72for Tb4b4b4(Te6edf3result Tff7b72in Te6edf3presetResultsTb4b4b4) Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3id Tff7b72!Tff7b72= Te6edf3bestTb4b4b4.Te6edf3idTb4b4b4) Tb4b4b4{
Te6edf3addTb4b4b4(Te6edf3buildAlternativeLineTb4b4b4(Te6edf3resultTb4b4b4)Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Te6edf3addTb4b4b4(Te6edf3buildCongestionNoteTb4b4b4(Te6edf3presetResultsTb4b4b4)Tb4b4b4)
Te6edf3addTb4b4b4(Te6edf3buildTrafficMixNoteTb4b4b4(Te6edf3presetResultsTb4b4b4)Tb4b4b4)
Te6edf3addTb4b4b4(Te6edf3buildRecommendationTb4b4b4(Te6edf3bestTb4b4b4, Te6edf3sessionTb4b4b4)Tb4b4b4)
Tb4b4b4}

Tff7b72return Te6edf3linesTb4b4b4.Te6edf3filterNotNullTb4b4b4(Tb4b4b4)Tb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Ta5d6ff Ta5d6ff"Tb4b4b4)
Tb4b4b4}

Tff7b72fun Td2a8ffgeneratePresetSummaryTb4b4b4(Te6edf3resultTb4b4b4: Te6edf3DiscoveryPresetResultEntityTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Te6edf3buildString Tb4b4b4{
Tff7b72val Te6edf3info Tff7b72= Te6edf3LoRaPresetReferenceTb4b4b4.Te6edf3getInfoTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3presetNameTb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Tffd700${Te6edf3resultTb4b4b4.Te6edf3presetNameTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3info Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff (Tffd700${Te6edf3infoTb4b4b4.Te6edf3dataRateTffd700}Ta5d6ff, Tffd700${Te6edf3infoTb4b4b4.Te6edf3linkBudgetTffd700}Ta5d6ff link budget)Ta5d6ff"Tb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff: Tffd700${Te6edf3resultTb4b4b4.Te6edf3uniqueNodesTffd700}Ta5d6ff nodesTa5d6ff"Tb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff (Tffd700${Te6edf3resultTb4b4b4.Te6edf3directNeighborCountTffd700}Ta5d6ff direct, Tffd700${Te6edf3resultTb4b4b4.Te6edf3meshNeighborCountTffd700}Ta5d6ff mesh)Ta5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgChannelUtilization Tff7b72> T79c0ff0.0Tb4b4b4) Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff, Tffd700${Te6edf3formatPercentTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgChannelUtilizationTb4b4b4)Tffd700}Ta5d6ff channel utilizationTa5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgChannelUtilization Tff7b72> Te6edf3HIGH_CONGESTION_THRESHOLDTb4b4b4) Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff (congested)Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3messageCount Tff7b72+ Te6edf3resultTb4b4b4.Te6edf3sensorPacketCount Tff7b72>Tff7b72= Te6edf3TRAFFIC_MIN_PACKET_THRESHOLDTb4b4b4) Tb4b4b4{
Tff7b72val Te6edf3dominant Tff7b72= Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3messageCount Tff7b72>Tff7b72= Te6edf3resultTb4b4b4.Te6edf3sensorPacketCountTb4b4b4) Ta5d6ff"Ta5d6ffchatTa5d6ff" Tff7b72else Ta5d6ff"Ta5d6ffsensorTa5d6ff"
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff, Tffd700$Te6edf3dominantTa5d6ff-dominated trafficTa5d6ff"Tb4b4b4)
Tb4b4b4}
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff.Ta5d6ff"Tb4b4b4)
Tb4b4b4}

T8b949e/** Build AI-style prompt for session-level analysis. Used by AI providers. */
Tff7b72fun Td2a8ffbuildSessionPromptTb4b4b4(Te6edf3sessionTb4b4b4: Te6edf3DiscoverySessionEntityTb4b4b4, Te6edf3presetResultsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DiscoveryPresetResultEntityTff7b72>Tb4b4b4)Tb4b4b4: Tffa657String Tff7b72=
Te6edf3buildString Tb4b4b4{
Te6edf3appendLineTb4b4b4(
Ta5d6ff"Ta5d6ffAnalyze this Meshtastic mesh radio discovery scan and recommend the best modem preset. Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffBe concise (3-4 sentences).Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3appendLineTb4b4b4(Tb4b4b4)
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ffSession: Tffd700${Te6edf3sessionTb4b4b4.Te6edf3totalUniqueNodesTffd700}Ta5d6ff unique nodes, status: Tffd700${Te6edf3sessionTb4b4b4.Te6edf3completionStatusTffd700}Ta5d6ff"Tb4b4b4)
Te6edf3appendLineTb4b4b4(Tb4b4b4)
Te6edf3appendTb4b4b4(Te6edf3LoRaPresetReferenceTb4b4b4.Te6edf3buildReferenceBlockTb4b4b4(Te6edf3presetResultsTb4b4b4.Te6edf3map Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3presetName Tb4b4b4}Tb4b4b4)Tb4b4b4)
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ffChannel util >25% indicates congestion; >50% causes significant packet loss.Ta5d6ff"Tb4b4b4)
Te6edf3appendLineTb4b4b4(Tb4b4b4)
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ffScan Results:Ta5d6ff"Tb4b4b4)
Tff7b72for Tb4b4b4(Te6edf3result Tff7b72in Te6edf3presetResultsTb4b4b4) Tb4b4b4{
Te6edf3appendLineTb4b4b4(Te6edf3formatPresetDataBlockTb4b4b4(Te6edf3resultTb4b4b4)Tb4b4b4)
Tb4b4b4}
Te6edf3appendLineTb4b4b4(Tb4b4b4)
Te6edf3appendTb4b4b4(
Ta5d6ff"Ta5d6ffBased on the scan data and preset reference, recommend which preset is best for this location. Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffConsider node density, infrastructure count, channel utilization, airtime, and traffic mix. Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffIf congestion is high, recommend a faster preset.Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Tb4b4b4}

T8b949e/** Build AI-style prompt for per-preset analysis. Used by AI providers. */
Tff7b72fun Td2a8ffbuildPresetPromptTb4b4b4(Te6edf3resultTb4b4b4: Te6edf3DiscoveryPresetResultEntityTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Te6edf3buildString Tb4b4b4{
Te6edf3appendLineTb4b4b4(
Ta5d6ff"Ta5d6ffBriefly summarize (1-2 sentences) the performance of the Tffd700${Te6edf3resultTb4b4b4.Te6edf3presetNameTffd700}Ta5d6ff Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffMeshtastic modem preset based on this scan data.Ta5d6ff"Tb4b4b4,
Tb4b4b4)
Te6edf3appendLineTb4b4b4(Tb4b4b4)
Tff7b72val Te6edf3ref Tff7b72= Te6edf3LoRaPresetReferenceTb4b4b4.Te6edf3formatReferenceTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3presetNameTb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3ref Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ffPreset info: Tffd700$Te6edf3refTa5d6ff"Tb4b4b4)
Te6edf3appendLineTb4b4b4(Ta5d6ff"Ta5d6ffChannel util >25% indicates congestion; >50% causes significant packet loss.Ta5d6ff"Tb4b4b4)
Te6edf3appendLineTb4b4b4(Tb4b4b4)
Te6edf3appendLineTb4b4b4(Te6edf3formatPresetDataBlockTb4b4b4(Te6edf3resultTb4b4b4)Tb4b4b4)
Te6edf3appendLineTb4b4b4(Tb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ffNote if this preset is well-suited for the observed traffic pattern and node density.Ta5d6ff"Tb4b4b4)
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffformatPresetDataBlockTb4b4b4(Te6edf3resultTb4b4b4: Te6edf3DiscoveryPresetResultEntityTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Te6edf3buildString Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff Tffd700${Te6edf3resultTb4b4b4.Te6edf3presetNameTffd700}Ta5d6ff: Ta5d6ff"Tb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ffNodes: Tffd700${Te6edf3resultTb4b4b4.Te6edf3uniqueNodesTffd700}Ta5d6ff Ta5d6ff"Tb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff(Direct: Tffd700${Te6edf3resultTb4b4b4.Te6edf3directNeighborCountTffd700}Ta5d6ff, Mesh: Tffd700${Te6edf3resultTb4b4b4.Te6edf3meshNeighborCountTffd700}Ta5d6ff)Ta5d6ff"Tb4b4b4)
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff, Messages: Tffd700${Te6edf3resultTb4b4b4.Te6edf3messageCountTffd700}Ta5d6ff, Sensor Packets: Tffd700${Te6edf3resultTb4b4b4.Te6edf3sensorPacketCountTffd700}Ta5d6ff"Tb4b4b4)
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgChannelUtilization Tff7b72> T79c0ff0.0Tb4b4b4) Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff, Channel Util: Tffd700${Te6edf3formatPercentTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgChannelUtilizationTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgAirtimeRate Tff7b72> T79c0ff0.0Tb4b4b4) Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff, Airtime: Tffd700${Te6edf3formatPercentTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgAirtimeRateTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3resultTb4b4b4.Te6edf3packetSuccessRate Tff7b72> T79c0ff0.0Tb4b4b4) Tb4b4b4{
Te6edf3appendTb4b4b4(Ta5d6ff"Ta5d6ff, Packet Success: Tffd700${Te6edf3formatPercentTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3packetSuccessRate Tff7b72* Te6edf3PERCENT_MULTIPLIERTb4b4b4)Tffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffbuildPresetComparisonLineTb4b4b4(
Te6edf3bestTb4b4b4: Te6edf3DiscoveryPresetResultEntityTb4b4b4,
Te6edf3allResultsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DiscoveryPresetResultEntityTff7b72>Tb4b4b4,
Tb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3info Tff7b72= Te6edf3LoRaPresetReferenceTb4b4b4.Te6edf3getInfoTb4b4b4(Te6edf3bestTb4b4b4.Te6edf3presetNameTb4b4b4)
Tff7b72val Te6edf3rateStr Tff7b72= Tff7b72if Tb4b4b4(Te6edf3info Tff7b72!Tff7b72= Tff7b72nullTb4b4b4) Ta5d6ff"Ta5d6ff (Tffd700${Te6edf3infoTb4b4b4.Te6edf3dataRateTffd700}Ta5d6ff)Ta5d6ff" Tff7b72else Ta5d6ff"Ta5d6ff"
Tff7b72if Tb4b4b4(Te6edf3allResultsTb4b4b4.Te6edf3size Tff7b72=Tff7b72= T79c0ff1Tb4b4b4) Tb4b4b4{
Tff7b72return Ta5d6ff"Tffd700${Te6edf3bestTb4b4b4.Te6edf3presetNameTffd700}Tffd700$Te6edf3rateStrTa5d6ff discovered Tffd700${Te6edf3bestTb4b4b4.Te6edf3uniqueNodesTffd700}Ta5d6ff node(s) Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffwith Tffd700${Te6edf3formatPercentTb4b4b4(Te6edf3bestTb4b4b4.Te6edf3avgChannelUtilizationTb4b4b4)Tffd700}Ta5d6ff channel utilization.Ta5d6ff"
Tb4b4b4}
Tff7b72return Ta5d6ff"Tffd700${Te6edf3bestTb4b4b4.Te6edf3presetNameTffd700}Tffd700$Te6edf3rateStrTa5d6ff discovered the most nodes (Tffd700${Te6edf3bestTb4b4b4.Te6edf3uniqueNodesTffd700}Ta5d6ff) Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffwith Tffd700${Te6edf3describeUtilizationTb4b4b4(Te6edf3bestTb4b4b4.Te6edf3avgChannelUtilizationTb4b4b4)Tffd700}Ta5d6ff channel utilization Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ff(Tffd700${Te6edf3formatPercentTb4b4b4(Te6edf3bestTb4b4b4.Te6edf3avgChannelUtilizationTb4b4b4)Tffd700}Ta5d6ff).Ta5d6ff"
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffbuildAlternativeLineTb4b4b4(Te6edf3resultTb4b4b4: Te6edf3DiscoveryPresetResultEntityTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3utilDesc Tff7b72= Te6edf3describeUtilizationTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgChannelUtilizationTb4b4b4)
Tff7b72val Te6edf3utilPct Tff7b72= Te6edf3formatPercentTb4b4b4(Te6edf3resultTb4b4b4.Te6edf3avgChannelUtilizationTb4b4b4)
Tff7b72return Ta5d6ff"Tffd700${Te6edf3resultTb4b4b4.Te6edf3presetNameTffd700}Ta5d6ff found Tffd700${Te6edf3resultTb4b4b4.Te6edf3uniqueNodesTffd700}Ta5d6ff node(s) Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffwith Tffd700$Te6edf3utilDescTa5d6ff channel utilization (Tffd700$Te6edf3utilPctTa5d6ff).Ta5d6ff"
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffbuildCongestionNoteTb4b4b4(Te6edf3resultsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DiscoveryPresetResultEntityTff7b72>Tb4b4b4)Tb4b4b4: Tffa657String? Tb4b4b4{
Tff7b72val Te6edf3congested Tff7b72= Te6edf3resultsTb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3avgChannelUtilization Tff7b72> Te6edf3HIGH_CONGESTION_THRESHOLD Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3congestedTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72return Tff7b72null
Tff7b72return Ta5d6ff"Ta5d6ffHigh congestion detected on Tffd700${Te6edf3congestedTb4b4b4.Te6edf3joinToString Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3presetName Tb4b4b4}Tffd700}Ta5d6ff; Ta5d6ff" Tff7b72+
Ta5d6ff"Ta5d6ffconsider a faster preset to reduce airtime.Ta5d6ff"
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffbuildTrafficMixNoteTb4b4b4(Te6edf3resultsTb4b4b4: Te6edf3ListTff7b72<Te6edf3DiscoveryPresetResultEntityTff7b72>Tb4b4b4)Tb4b4b4: Tffa657String? Tb4b4b4{
Tff7b72val Te6edf3significantResults Tff7b72=
Te6edf3resultsTb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3messageCount Tff7b72+ Tffa657itTb4b4b4.Te6edf3sensorPacketCount Tff7b72>Tff7b72= Te6edf3TRAFFIC_MIN_PACKET_THRESHOLD Tb4b4b4}
Tff7b72val Te6edf3chatDominant Tff7b72= Te6edf3significantResultsTb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3messageCount Tff7b72> Tffa657itTb4b4b4.Te6edf3sensorPacketCount Tb4b4b4}
Tff7b72val Te6edf3sensorDominant Tff7b72= Te6edf3significantResultsTb4b4b4.Te6edf3filter Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3sensorPacketCount Tff7b72> Tffa657itTb4b4b4.Te6edf3messageCount Tb4b4b4}
Tff7b72val Te6edf3parts Tff7b72= Te6edf3buildList Tb4b4b4{
Tff7b72if Tb4b4b4(Te6edf3chatDominantTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3addTb4b4b4(Ta5d6ff"Ta5d6ffchat-dominated on Tffd700${Te6edf3chatDominantTb4b4b4.Te6edf3joinToString Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3presetName Tb4b4b4}Tffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3sensorDominantTb4b4b4.Te6edf3isNotEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tb4b4b4{
Te6edf3addTb4b4b4(Ta5d6ff"Ta5d6ffsensor-dominated on Tffd700${Te6edf3sensorDominantTb4b4b4.Te6edf3joinToString Tb4b4b4{ Tffa657itTb4b4b4.Te6edf3presetName Tb4b4b4}Tffd700}Ta5d6ff"Tb4b4b4)
Tb4b4b4}
Tb4b4b4}
Tff7b72if Tb4b4b4(Te6edf3partsTb4b4b4.Te6edf3isEmptyTb4b4b4(Tb4b4b4)Tb4b4b4) Tff7b72return Tff7b72null
Tff7b72return Ta5d6ff"Ta5d6ffTraffic mix: Tffd700${Te6edf3partsTb4b4b4.Te6edf3joinToStringTb4b4b4(Ta5d6ff"Tb4b4b4; Ta5d6ff"Tb4b4b4)Tffd700}Ta5d6ff.Ta5d6ff"
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffbuildRecommendationTb4b4b4(Te6edf3bestTb4b4b4: Te6edf3DiscoveryPresetResultEntityTb4b4b4, Te6edf3sessionTb4b4b4: Te6edf3DiscoverySessionEntityTb4b4b4)Tb4b4b4: Tffa657String Tb4b4b4{
Tff7b72val Te6edf3status Tff7b72= Tff7b72if Tb4b4b4(Te6edf3sessionTb4b4b4.Te6edf3completionStatus Tff7b72=Tff7b72= Ta5d6ff"Ta5d6ffcompleteTa5d6ff"Tb4b4b4) Ta5d6ff"Ta5d6ffcompletedTa5d6ff" Tff7b72else Ta5d6ff"Ta5d6ffpartially completedTa5d6ff"
Tff7b72return Ta5d6ff"Ta5d6ffRecommendation: Use Tffd700${Te6edf3bestTb4b4b4.Te6edf3presetNameTffd700}Ta5d6ff for this location (scan Tffd700$Te6edf3statusTa5d6ff).Ta5d6ff"
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffdescribeUtilizationTb4b4b4(Te6edf3percentTb4b4b4: Tffa657DoubleTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Tff7b72when Tb4b4b4{
Te6edf3percent Tff7b72< Te6edf3LOW_UTIL_THRESHOLD Tff7b72-Tff7b72> Ta5d6ff"Ta5d6fflowTa5d6ff"
Te6edf3percent Tff7b72< Te6edf3MODERATE_UTIL_THRESHOLD Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffmoderateTa5d6ff"
Te6edf3percent Tff7b72< Te6edf3HIGH_UTIL_THRESHOLD Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffhighTa5d6ff"
Tff7b72else Tff7b72-Tff7b72> Ta5d6ff"Ta5d6ffvery highTa5d6ff"
Tb4b4b4}

Tff7b72private Tff7b72fun Td2a8ffformatPercentTb4b4b4(Te6edf3valueTb4b4b4: Tffa657DoubleTb4b4b4)Tb4b4b4: Tffa657String Tff7b72= Ta5d6ff"Tffd700${Te6edf3NumberFormatterTb4b4b4.Te6edf3formatTb4b4b4(Te6edf3valueTb4b4b4, T79c0ff1Tb4b4b4)Tffd700}Ta5d6ff%Ta5d6ff"

Tff7b72companion Tff7b72object Tb4b4b4{
Tff7b72private Tff7b72const Tff7b72val Te6edf3LOW_UTIL_THRESHOLD Tff7b72= T79c0ff2T79c0ff5.0
Tff7b72private Tff7b72const Tff7b72val Te6edf3MODERATE_UTIL_THRESHOLD Tff7b72= T79c0ff5T79c0ff0.0
Tff7b72private Tff7b72const Tff7b72val Te6edf3HIGH_UTIL_THRESHOLD Tff7b72= T79c0ff7T79c0ff5.0
Tff7b72private Tff7b72const Tff7b72val Te6edf3HIGH_CONGESTION_THRESHOLD Tff7b72= T79c0ff2T79c0ff5.0
Tff7b72private Tff7b72const Tff7b72val Te6edf3PERCENT_MULTIPLIER Tff7b72= T79c0ff1T79c0ff0T79c0ff0.0
Tff7b72private Tff7b72const Tff7b72val Te6edf3TRAFFIC_MIN_PACKET_THRESHOLD Tff7b72= T79c0ff5
Tb4b4b4}
Tb4b4b4}

Served by rngit 1.5.0 - Generated in 0.13s